﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Diagnostics;
using System.Reflection;
using System.ComponentModel;

namespace GameEditor.Common
{

    class FlagsEditor : CheckedListBox
    {
        public class Item
        {
            public int Value { get; set; }
            public string Name { get; set; }
            public override string ToString()
            {
                return Name;
            }
        }
        public FlagsEditor()
        {

        }
        public void SetItems(Item[] items)
        {
            Items.AddRange(items);
            Height = (int)(Font.GetHeight() * (3 + items.Length)) + 10;
        }

        public int Value
        {
            get
            {
                int ret = 0;
                foreach (Object obj in this.CheckedItems)
                {
                    ret |= (obj as Item).Value;
                }
                return ret;
            }
            set
            {
                ClearSelected();
                for (int i = 0; i < Items.Count; i++)
                {
                    Item item = Items[i] as Item;
                    if ((item.Value & value) != 0)
                        SetItemChecked(i, true);
                }


            }
        }


    }
    public class FlagsTypeEditor : UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            Debug.Assert(service != null);
            FlagsEditor editor = new FlagsEditor();

            Type propertyType = context.PropertyDescriptor.PropertyType;
            //获取可用值类型
            List<FlagsEditor.Item> items = new List<FlagsEditor.Item>();
            int all = 0;
            FlagsEditor.Item allItem = null;
            foreach (FieldInfo fi in propertyType.GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                int v = (fi.GetValue(context.Instance) as IConvertible).ToInt32(null);
                if (v == 0)//因为标志位与0或运算等于其自身，所以0值没有意义
                    continue;

                FlagsEditor.Item item = new FlagsEditor.Item { Name = fi.Name, Value = v };
                //检查是否有FieldAlias属性
                if (Attribute.IsDefined(fi, typeof(FieldAliasAttribute)))
                {
                    FieldAliasAttribute attr = (FieldAliasAttribute)Attribute.GetCustomAttribute(fi, typeof(FieldAliasAttribute));
                    item.Name = attr.AliasName;
                }
                all |= item.Value;
                if (all == v)
                    allItem = item;
                items.Add(item);
            }
            //如果值有多个，则去掉allItem
            if (items.Count > 1)
                items.Remove(allItem);

            editor.SetItems(items.ToArray());
            editor.Value = (value as IConvertible).ToInt32(null);
            service.DropDownControl(editor);
            return editor.Value;
        }

    }
}
